#ifndef db_Record_Def_h
#define db_Record_Def_h

#include <string>
#include <map>


namespace serika
{
	namespace db
	{
	#define DECLARE_RECORD(className, tableName, primaryKey) \
	public:\
		className(FieldMap* fields);	\
		className(FieldMap* fields, bool readOnly);	 \
		static const char* GetTableName() { static const char* tn = #tableName; return tn; } \
		static const char* GetPrimaryKey() { static const char* pk = #primaryKey; return pk; } \
		virtual const char* GetTableNameI() const { return className::GetTableName(); }	\
		virtual const char* GetPrimaryKeyI() const { return className::GetPrimaryKey(); }  \
		virtual bool IsCachableI() const { return className::mCachable; }		\
		virtual Adapter* GetAdapterI() const { return className::mAdapter; }		\
		static className* Create(FieldMap* fieldMap, bool throwOnError = false) { return RecordBase::Create<className>(fieldMap, throwOnError); }	\
		static bool Create(std::vector<className*>& results, std::vector<FieldMap*>& fieldMaps, bool throwOnError = false) { return RecordBase::Create<className>(results, fieldMaps, throwOnError); }	\
		static className* Find(int id) { return RecordBase::Find<className>(id); }	\
		static className* Find(const Any& value, const std::string& column = "") { return RecordBase::Find<className>(value, column); }	\
		static int Find(std::vector<className*>& resultSet, const std::vector<int>& ids) { return RecordBase::Find<className>(resultSet, ids); }	\
		static int Find(std::vector<className*>& resultSet, const std::vector<Any>& values, const std::string& column = "") { return RecordBase::Find<className>(resultSet, values, column); }	\
		static className* FindFirst(const std::string& conditions = "", const std::string& select = "*", const std::string& joins = "", const std::string& order = "", const std::string& group = "", const std::string& having = "")	\
		{ return RecordBase::FindFirst<className>(conditions, select, joins, order, group, having); }	\
		static int FindAll(std::vector<className*>& resultSet, const std::string& conditions = "", int offset = 0, int limit = 0, const std::string& select = "*", const std::string& joins = "", const std::string& order = "", const std::string& group = "", const std::string& having = "")	\
		{ return RecordBase::FindAll<className>(resultSet, conditions, offset, limit, select, joins, order, group, having); }	\
		static int Count(const std::string& column = "*", const std::string& conditions = "", const std::string& joins = "") { return RecordBase::Count<className>(column, conditions, joins);}	\
		static Pagination<className>* Paginate(int page, int perPage, const std::string& conditions = "", const std::string& select = "*", const std::string& joins = "", const std::string& order = "") { return RecordBase::Paginate<className>(page, perPage, conditions, select, joins, order); }	\
		static int UpdateAll(const std::string& settings, const std::string& conditions) { return RecordBase::UpdateAll<className>(settings, conditions); }	\
		void Destroy() { RecordBase::Destroy(); }	\
		static bool Delete(int id) { return RecordBase::Delete<className>(id); } \
		static int Delete(const Any& value, const std::string& column = "") { return RecordBase::Delete<className>(value, column); }	\
		static int Delete(const std::vector<Any>& values, const std::string& column = "") { return RecordBase::Delete<className>(values, column); }	\
		static int DeleteAll(const std::string& conditions = "") { return RecordBase::DeleteAll<className>(conditions); }		\
		static int Destroy(const Any& value, const std::string& column = "") { return RecordBase::Destroy<className>(value, column); }	\
		static int Destroy(const std::vector<Any>& values, const std::string& column = "") { return RecordBase::Destroy<className>(values, column); }	\
		static int DestroyAll(const std::string& conditions = "") { return RecordBase::DestroyAll<className>(conditions); }	\
		static bool IsCachable() { return mCachable; }	\
		static void SetCachable(bool cachable) { mCachable = cachable; }		\
	private: \
		static AdapterPtr mAdapter; \
		static bool mCachable;		\
		friend class RecordBase;
	
	#define DECLARE_DEFAULT_RECORD(className, tableName) DECLARE_RECORD(className, tableName, id)
	
	#define IMPLEMENT_RECORD(className) \
		AdapterPtr className::mAdapter = RecordBase::mDefaultAdapter;	\
		bool className::mCachable = true;	\
		className::className(FieldMap* fields)	\
			:RecordBase(fields, false) \
		{														\
			if (fields == 0)									\
			{													\
				throw RecordException(-1, _T("Create record by NULL field map"));	\
			}																	\
			FieldMap::iterator itr = fields->find(className::GetPrimaryKey());	\
			if (itr != fields->end())											\
			{																	\
				fields->erase(itr);												\
			}																	\
			mModified = true;													\
		}																		\
		className::className(FieldMap* fields, bool readOnly) : RecordBase(fields, readOnly) {  }
	
		//typedef std::map<ut::String, Any> FieldMap;
		typedef std::map<std::string, Any> FieldMap;
	}
}
	
#endif

